# mg002/sweetest/globals.py
# -*- coding: utf-8 -*-
"""
全局变量管理（兼容旧框架调用）
说明：
- 为避免循环导入，不在模块顶层依赖项目内部模块（如 sweetest.log / sweetest.utility）。
- 使用标准 logging.getLogger("sweetest") 作为默认 logger（若你在 log.py 中配置了 logger，后续会覆盖/使用）。
- init_driver() 会在运行时尝试延迟导入 sweetest.keywords.windows（优先尝试 WindowsDriverProxy，再回退到 Windows(Playwright-Python)）
"""

from datetime import datetime
import time
import traceback
import logging

# 使用标准 logging，避免在模块导入阶段依赖项目内部 logger（会引起循环）
logger = logging.getLogger("sweetest")


def now(fmt="%Y-%m-%d %H:%M:%S"):
    """返回可读的本地时间字符串"""
    return datetime.now().strftime(fmt)


def timestamp():
    """返回毫秒级时间戳（int）"""
    return int(round(time.time() * 1000))


class GlobalContext:
    def __init__(self):
        # 计时 / plan 信息
        self.plan_name = ''
        self.sheet_name = ''
        self.start_time = now("%Y%m%d%H%M%S")
        self.start_timestamp = timestamp()
        self.current_page = ''

        # 报告 / 数据收集结构
        self.plan_data = {}
        self.testsuite_data = {}
        self.report_data = {}

        # 计数器
        self.no = 1

        # 驱动 / 平台（兼容旧逻辑）
        self.driver = None          # driver 或代理对象
        self.windows = {}           # 旧逻辑占位（以前用于 pywinauto app）
        self.snippet = {}
        self.caseset = {}
        self.casesets = []

        # 运行时临时数据结构
        self.test_data = {'_last_': False}
        self.var = {}
        self.db = {}
        self.http = {}
        self.action = {}
        self.wait_times = 0

        # 配置/能力
        self.desired_caps = {}
        self.server_url = ''
        self.platform = ''       # platformName，例 'windows'
        self.browserName = ''
        self.headless = False
        self.snapshot = False
        self.executable_path = None
        self.mobile = False

        # 其他占位
        self.junit = None
        self.junit_suite = None
        self.ts = None  # testsuite 实例占位

    def init(self, desired_caps=None, server_url=''):
        """
        兼容旧框架的 init：设置 desired_caps / server_url / 起始时间等
        注意：不要在这里做会触发循环导入的操作（如导入 utility）
        """
        self.desired_caps = desired_caps or {}
        self.server_url = server_url or ''
        self.start_time = now("%Y%m%d%H%M%S")
        self.start_timestamp = timestamp()

        # 解析常见 capability 字段
        try:
            caps = dict(self.desired_caps)
            self.platform = caps.get('platformName', '').lower()
            self.browserName = caps.get('browserName', '')
            self.headless = caps.get('headless', False)
            self.snapshot = caps.get('snapshot', False)
            self.executable_path = caps.get('executable_path', None)
            self.mobile = caps.get('mobile', False)
        except Exception:
            # 这里使用标准 logger，不依赖 sweetest.log 模块（避免循环）
            logger.warning("解析 desired_caps 失败，继续使用默认值")
            logger.debug(traceback.format_exc())

        # 保证容器属性存在，避免后续访问 AttributeError
        self.plan_data = getattr(self, 'plan_data', {}) or {}
        self.testsuite_data = getattr(self, 'testsuite_data', {}) or {}
        self.report_data = getattr(self, 'report_data', {}) or {}
        self.test_data = getattr(self, 'test_data', {'_last_': False})

    def init_driver(self):
        """
        在运行时创建/启动平台 driver。
        - 优先尝试导入 sweetest.keywords.windows.WindowsDriverProxy（node worker 代理）
        - 若没有代理或代理初始化失败，再尝试回退到 sweetest.keywords.windows.Windows（Playwright-Python）
        这里的导入均是延迟导入（运行时）, 降低循环导入风险。
        """
        if self.driver is not None:
            return self.driver

        plat = (self.platform or '').lower()
        if plat in ('windows', 'desktop', 'electron', ''):
            # 先尝试 Node.js worker 代理类（如果你实现了）
            WindowsDriverProxy = None
            try:
                # 延迟导入代理类（避免模块在顶层互相导入）
                from sweetest.keywords.windows import WindowsDriverProxy as _proxy
                WindowsDriverProxy = _proxy
            except Exception:
                WindowsDriverProxy = None

            if WindowsDriverProxy:
                try:
                    self.driver = WindowsDriverProxy()
                    # 兼容旧逻辑：放到 windows['default']
                    self.windows['default'] = self.driver
                    logger.info("WindowsDriverProxy 初始化成功（node worker proxy）")
                    return self.driver
                except Exception:
                    logger.exception("WindowsDriverProxy 初始化失败，尝试回退")

            # 回退到 Playwright-Python 的 Windows 类（如果存在）
            try:
                from sweetest.keywords.windows import Windows as _windows
                w = _windows()
                # 尝试启动/attach（注意 windows_tools.py 的实现必须支持长期运行）
                try:
                    if hasattr(w, 'start_playwright'):
                        w.start_playwright()
                    elif hasattr(w, 'start'):
                        w.start()
                except Exception:
                    logger.exception("调用 Windows.start_playwright/start 失败（可能是实现问题）")
                self.driver = w
                self.windows['default'] = w
                logger.info("Playwright-Python Windows driver 已创建（或已启动）")
                return self.driver
            except Exception:
                logger.exception("回退到 Playwright-Python Windows 初始化失败")
                return None
        else:
            logger.warning(f"init_driver: 未实现平台 '{self.platform}' 的 driver 创建")
            return None

    def set_driver(self):
        """
        兼容旧框架调用点：Autotest.run 会调用 g.set_driver()
        在这里初始化运行时数据结构并尝试 init_driver()
        """
        # 初始化/重置运行时容器
        self.test_data = {'_last_': False}
        self.var = {}
        self.casesets = []
        self.db = {}
        self.http = {}
        self.windows = {}
        self.action = {}
        self.wait_times = 0
        self.snippet = {}
        self.caseset = {}
        self.current_page = ''

        if not hasattr(self, 'no'):
            self.no = 1

        logger.info("g.set_driver(): 初始化运行时容器完成")

        # 创建 driver（如果未创建）
        try:
            self.init_driver()
        except Exception:
            logger.exception("g.set_driver -> init_driver 出现异常")

        return True

    def plan_end(self):
        """
        测试计划结束时调用，返回 plan_data 并保证 end_timestamp 存在
        """
        try:
            self.plan_data.setdefault('plan', self.plan_name or '')
            self.plan_data.setdefault('start_timestamp', getattr(self, 'start_timestamp', timestamp()))
            self.plan_data['end_timestamp'] = timestamp()
        except Exception:
            logger.exception("plan_end 组装 plan_data 时出错")
        return self.plan_data


# 全局实例
g = GlobalContext()

# 导出便捷名称（其他模块可能直接 import timestamp, now）
__all__ = ['g', 'timestamp', 'now']
